<!DOCTYPE html>
<html>

<head>
    <title>crop</title>
    <script type="text/javascript" src="jquery.js"></script>
</head>

<body>
    <input type="file" name="" accept="image/gif, image/jpeg,image/png" id="upload">
    <canvas id="showimg" style="border:1px solid #aaa;"></canvas>
    <p>移动:</p>
    <input type="range" min="0" max="2" id="move" step="0.01" value="1" class="range-control" />
    <br/>
    <button id="crop">剪裁输出</button><img id="img" src="" style="border:1px solid #aaa;">
</body>
<script type="text/javascript">
-(function($) {
    var crop = {
        init: function() {
            this.img = new Image();
            this.can = document.getElementById('showimg');
            var ctx = this.ctx = this.can.getContext("2d");
            this.width = this.can.width = 500;
            this.height = this.can.height = 400;
            ctx.fillStyle = "#aaa";
            ctx.fillRect(0, 0, 500, 400);
            ctx.beginPath();
            ctx.moveTo(100, 100);
            ctx.lineTo(400, 100);
            ctx.lineTo(400, 300);
            ctx.lineTo(100, 300);
            ctx.lineTo(100, 100);
            ctx.lineWidth = 3;
            ctx.strokeStyle = '#333'
            ctx.stroke();
            ctx.clip();
            ctx.closePath();
            this.clear();
            this.addListen();
        },
        render(src) {
            this.img = new Image();
            this.img.onload = function() {
                var $this = crop;
                $this.img_width = $this.img.width; //原图像横坐标
                $this.img_height = $this.img.height; //原图像纵坐标
                $this.fictitious_imgwidth = $this.img_width; //被缩放的图像横坐标
                $this.fictitious_imgheight = $this.img_height; //被缩放的图像纵坐标
                //因为后面图像的变化后长度都不是原长度了,后面使用图像长度是就使用fictitious属性
                $this.init_x = $this.width * 0.5; //图片中心点横坐标
                $this.init_y = $this.height * 0.5; //图片中心点纵坐标
                //绘图时同过中心点减去fictitious/2长度来确定图像左上角的坐标
                $this.ctx.drawImage($this.img, $this.init_x - $this.img_width / 2, $this.init_y - $this.img_height / 2, $this.img_width, $this.img_height);
            };
            this.img.src = src;
        },
        change: function() {
            this.clear();
            $('#move').val(1) //根据实际需要进行初始化
            var reader = new FileReader();
            var img = $('#upload').get(0).files[0];

            reader.onload = function(e) {
                crop.render(e.target.result);
            };

            reader.readAsDataURL(img);
        },
        translate: function() {
            var val = document.getElementById("move").value;
            this.clear();
            this.fictitious_imgwidth = this.img_width * val;
            this.fictitious_imgheight = this.img_height * val;
            this.ctx.drawImage(this.img, this.init_x - this.fictitious_imgwidth / 2, this.init_y - this.fictitious_imgheight / 2, this.fictitious_imgwidth, this.fictitious_imgheight);
        },
        mouseDown: function(e) {
            this.orign_x = e.offsetX;
            this.orign_y = e.offsetY;
            this.judgmentIsInImg(e); //判断点击是否在图像内
        },
        mouseMove: function(e) {
            var e = e || event;
            if (this.flag) {
                this.distance_x = e.offsetX - this.orign_x; //鼠标移动的长度
                this.distance_y = e.offsetY - this.orign_y;
                this.clear();
                this.substitute_x = this.init_x + this.distance_x;
                this.substitute_y = this.init_y + this.distance_y;
                this.ctx.drawImage(this.img, this.substitute_x - this.fictitious_imgwidth / 2, this.substitute_y - this.fictitious_imgheight / 2, this.fictitious_imgwidth, this.fictitious_imgheight);
            }
        },
        mouseLeave: function() {
            if (this.flag) {
                this.init_x = this.substitute_x;
                this.init_y = this.substitute_y;
                this.flag = false;
            }

        },
        out: function() {
            //输出图像
            var crop_canvas = document.createElement('canvas');
            crop_canvas.width = 300;
            crop_canvas.height = 200;
            crop_ctx = crop_canvas.getContext('2d');
            crop_ctx.fillStyle = "#fff";
            crop_ctx.fillRect(0, 0, 300, 200);
            crop_ctx.drawImage(this.img, this.init_x - this.fictitious_imgwidth / 2 - 100, this.init_y - this.fictitious_imgheight / 2 - 100, this.fictitious_imgwidth, this.fictitious_imgheight);
            //这边的减去100 是原 canvas 阴影边框的长度
            var fullQuality = crop_canvas.toDataURL('image/jpeg', 1.0);
            $('#img').attr('src', fullQuality);
        },
        judgmentIsInImg: function(e) {
            var e = e || event;

            var ll = this.init_x - this.fictitious_imgwidth / 2;
            var lt = this.init_y - this.fictitious_imgheight / 2;
            var rl = this.init_x + this.fictitious_imgwidth / 2;
            var rt = this.init_y + this.fictitious_imgheight / 2;
            //图像四个角的坐标

            var x = e.clientX - this.can.getBoundingClientRect().left;
            var y = e.clientY - this.can.getBoundingClientRect().top;

            if (ll < x && x < rl && lt < y && y < rt) {
                this.flag = true;
            } else {
                this.flag = false;
            }

        },
        clear: function() {
            this.ctx.clearRect(0, 0, this.width, this.height);
        },
        addListen: function() {
            $('#upload').on('change', this.change.bind(this));
            $('#move').on('input', this.translate.bind(this));
            $('#showimg').on('mousedown', this.mouseDown.bind(this))
                .on('mousemove', this.mouseMove.bind(this))
                .on('mouseleave mouseup', this.mouseLeave.bind(this));
            $('#crop').on('click', this.out.bind(this));
        }
    }
    return crop.init();
})(jQuery)
</script>

</html>